/* *
 *
 *  Popup generator for Stock tools
 *
 *  (c) 2009-2017 Sebastian Bochan
 *
 *  License: www.highcharts.com/license
 *
 * */
"use strict";
import H from "../parts/Globals.js";

import U from "../parts/Utilities.js";
var defined = U.defined,
  isArray = U.isArray,
  isObject = U.isObject,
  isString = U.isString,
  objectEach = U.objectEach,
  pick = U.pick,
  wrap = U.wrap;

var addEvent = H.addEvent,
  createElement = H.createElement,
  indexFilter = /\d/g,
  PREFIX = "highcharts-",
  DIV = "div",
  INPUT = "input",
  LABEL = "label",
  BUTTON = "button",
  SELECT = "select",
  OPTION = "option",
  SPAN = "span",
  UL = "ul",
  LI = "li",
  H3 = "h3";

// onContainerMouseDown blocks internal popup events, due to e.preventDefault.
// Related issue #4606

wrap(H.Pointer.prototype, "onContainerMouseDown", function (proceed, e) {
  var popupClass = e.target && e.target.className;

  // elements is not in popup
  if (
    !(isString(popupClass) && popupClass.indexOf(PREFIX + "popup-field") >= 0)
  ) {
    proceed.apply(this, Array.prototype.slice.call(arguments, 1));
  }
});

H.Popup = function (parentDiv, iconsURL) {
  this.init(parentDiv, iconsURL);
};

H.Popup.prototype = {
  /**
   * Initialize the popup. Create base div and add close button.
   * @private
   * @param {HTMLDOMElement} - container where popup should be placed
   * @param {Object} - user options
   * @return {HTMLDOMElement} - return created popup's div
   */
  init: function (parentDiv, iconsURL) {
    // create popup div
    this.container = createElement(
      DIV,
      {
        className: PREFIX + "popup",
      },
      null,
      parentDiv
    );

    this.lang = this.getLangpack();
    this.iconsURL = iconsURL;

    // add close button
    this.addCloseBtn();
  },
  /**
   * Create HTML element and attach click event (close popup).
   * @private
   */
  addCloseBtn: function () {
    var _self = this,
      closeBtn;

    // create close popup btn
    closeBtn = createElement(
      DIV,
      {
        className: PREFIX + "popup-close",
      },
      null,
      this.container
    );

    closeBtn.style["background-image"] = "url(" + this.iconsURL + "close.svg)";

    ["click", "touchstart"].forEach(function (eventName) {
      addEvent(closeBtn, eventName, function () {
        _self.closePopup();
      });
    });
  },
  /**
   * Create two columns (divs) in HTML.
   * @private
   * @param {HTMLDOMElement} - container of columns
   * @return {Object} - reference to two HTML columns
   */
  addColsContainer: function (container) {
    var rhsCol, lhsCol;

    // left column
    lhsCol = createElement(
      DIV,
      {
        className: PREFIX + "popup-lhs-col",
      },
      null,
      container
    );

    // right column
    rhsCol = createElement(
      DIV,
      {
        className: PREFIX + "popup-rhs-col",
      },
      null,
      container
    );

    // wrapper content
    createElement(
      DIV,
      {
        className: PREFIX + "popup-rhs-col-wrapper",
      },
      null,
      rhsCol
    );

    return {
      lhsCol: lhsCol,
      rhsCol: rhsCol,
    };
  },
  /**
   * Create input with label.
   * @private
   * @param {String} - chain of fields i.e params.styles.fontSize
   * @param {String} - indicator type
   * @param {HTMLDOMElement} - container where elements should be added
   * @param {String} - dafault value of input i.e period value is 14,
   * extracted from defaultOptions (ADD mode) or series options (EDIT mode)
   */
  addInput: function (option, type, parentDiv, value) {
    var optionParamList = option.split("."),
      optionName = optionParamList[optionParamList.length - 1],
      lang = this.lang,
      inputName = PREFIX + type + "-" + optionName;

    if (!inputName.match(indexFilter)) {
      // add label
      createElement(
        LABEL,
        {
          innerHTML: lang[optionName] || optionName,
          htmlFor: inputName,
        },
        null,
        parentDiv
      );
    }

    // add input
    createElement(
      INPUT,
      {
        name: inputName,
        value: value[0],
        type: value[1],
        className: PREFIX + "popup-field",
      },
      null,
      parentDiv
    ).setAttribute(PREFIX + "data-name", option);
  },
  /**
   * Create button.
   * @private
   * @param {HTMLDOMElement} - container where elements should be added
   * @param {String} - text placed as button label
   * @param {String} - add | edit | remove
   * @param {Function} - on click callback
   * @param {HTMLDOMElement} - container where inputs are generated
   * @return {HTMLDOMElement} - html button
   */
  addButton: function (parentDiv, label, type, callback, fieldsDiv) {
    var _self = this,
      closePopup = this.closePopup,
      getFields = this.getFields,
      button;

    button = createElement(
      BUTTON,
      {
        innerHTML: label,
      },
      null,
      parentDiv
    );

    ["click", "touchstart"].forEach(function (eventName) {
      addEvent(button, eventName, function () {
        closePopup.call(_self);

        return callback(getFields(fieldsDiv, type));
      });
    });

    return button;
  },
  /**
   * Get values from all inputs and create JSON.
   * @private
   * @param {HTMLDOMElement} - container where inputs are created
   * @param {String} - add | edit | remove
   * @return {Object} - fields
   */
  getFields: function (parentDiv, type) {
    var inputList = parentDiv.querySelectorAll("input"),
      optionSeries = "#" + PREFIX + "select-series > option:checked",
      optionVolume = "#" + PREFIX + "select-volume > option:checked",
      linkedTo = parentDiv.querySelectorAll(optionSeries)[0],
      volumeTo = parentDiv.querySelectorAll(optionVolume)[0],
      seriesId,
      param,
      fieldsOutput;

    fieldsOutput = {
      actionType: type,
      linkedTo: linkedTo && linkedTo.getAttribute("value"),
      fields: {},
    };

    [].forEach.call(inputList, function (input) {
      param = input.getAttribute(PREFIX + "data-name");
      seriesId = input.getAttribute(PREFIX + "data-series-id");

      // params
      if (seriesId) {
        fieldsOutput.seriesId = input.value;
      } else if (param) {
        fieldsOutput.fields[param] = input.value;
      } else {
        // type like sma / ema
        fieldsOutput.type = input.value;
      }
    });

    if (volumeTo) {
      fieldsOutput.fields["params.volumeSeriesID"] =
        volumeTo.getAttribute("value");
    }

    return fieldsOutput;
  },
  /**
   * Reset content of the current popup and show.
   * @private
   * @param {Chart} - chart
   * @param {Function} - on click callback
   * @return {Object} - fields
   */
  showPopup: function () {
    var popupDiv = this.container,
      toolbarClass = PREFIX + "annotation-toolbar",
      popupCloseBtn = popupDiv.querySelectorAll(
        "." + PREFIX + "popup-close"
      )[0];

    // reset content
    popupDiv.innerHTML = "";

    // reset toolbar styles if exists
    if (popupDiv.className.indexOf(toolbarClass) >= 0) {
      popupDiv.classList.remove(toolbarClass);

      // reset toolbar inline styles
      popupDiv.removeAttribute("style");
    }

    // add close button
    popupDiv.appendChild(popupCloseBtn);
    popupDiv.style.display = "block";
  },
  /**
   * Hide popup.
   * @private
   */
  closePopup: function () {
    this.popup.container.style.display = "none";
  },
  /**
   * Create content and show popup.
   * @private
   * @param {String} - type of popup i.e indicators
   * @param {Chart} - chart
   * @param {Object} - options
   * @param {Function} - on click callback
   */
  showForm: function (type, chart, options, callback) {
    this.popup = chart.navigationBindings.popup;

    // show blank popup
    this.showPopup();

    // indicator form
    if (type === "indicators") {
      this.indicators.addForm.call(this, chart, options, callback);
    }

    // annotation small toolbar
    if (type === "annotation-toolbar") {
      this.annotations.addToolbar.call(this, chart, options, callback);
    }

    // annotation edit form
    if (type === "annotation-edit") {
      this.annotations.addForm.call(this, chart, options, callback);
    }

    // flags form - add / edit
    if (type === "flag") {
      this.annotations.addForm.call(this, chart, options, callback, true);
    }
  },
  /**
   * Return lang definitions for popup.
   * @private
   * @return {Object} - elements translations.
   */
  getLangpack: function () {
    return H.getOptions().lang.navigation.popup;
  },
  annotations: {
    /**
     * Create annotation simple form. It contains two buttons
     * (edit / remove) and text label.
     * @private
     * @param {Chart} - chart
     * @param {Object} - options
     * @param {Function} - on click callback
     */
    addToolbar: function (chart, options, callback) {
      var _self = this,
        lang = this.lang,
        popupDiv = this.popup.container,
        showForm = this.showForm,
        toolbarClass = PREFIX + "annotation-toolbar",
        button;

      // set small size
      if (popupDiv.className.indexOf(toolbarClass) === -1) {
        popupDiv.className += " " + toolbarClass;
      }

      // set position
      popupDiv.style.top = chart.plotTop + 10 + "px";

      // create label
      createElement(
        SPAN,
        {
          innerHTML: pick(
            // Advanced annotations:
            lang[options.langKey] || options.langKey,
            // Basic shapes:
            options.shapes && options.shapes[0].type
          ),
        },
        null,
        popupDiv
      );

      // add buttons
      button = this.addButton(
        popupDiv,
        lang.removeButton || "remove",
        "remove",
        callback,
        popupDiv
      );

      button.className += " " + PREFIX + "annotation-remove-button";
      button.style["background-image"] =
        "url(" + this.iconsURL + "destroy.svg)";

      button = this.addButton(
        popupDiv,
        lang.editButton || "edit",
        "edit",
        function () {
          showForm.call(_self, "annotation-edit", chart, options, callback);
        },
        popupDiv
      );

      button.className += " " + PREFIX + "annotation-edit-button";
      button.style["background-image"] = "url(" + this.iconsURL + "edit.svg)";
    },
    /**
     * Create annotation simple form.
     * It contains fields with param names.
     * @private
     * @param {Chart} - chart
     * @param {Object} - options
     * @param {Function} - on click callback
     * @param {Boolean} - if it is a form declared for init annotation
     */
    addForm: function (chart, options, callback, isInit) {
      var popupDiv = this.popup.container,
        lang = this.lang,
        bottomRow,
        lhsCol;

      // create title of annotations
      lhsCol = createElement(
        "h2",
        {
          innerHTML: lang[options.langKey] || options.langKey,
          className: PREFIX + "popup-main-title",
        },
        null,
        popupDiv
      );

      // left column
      lhsCol = createElement(
        DIV,
        {
          className: PREFIX + "popup-lhs-col " + PREFIX + "popup-lhs-full",
        },
        null,
        popupDiv
      );

      bottomRow = createElement(
        DIV,
        {
          className: PREFIX + "popup-bottom-row",
        },
        null,
        popupDiv
      );

      this.annotations.addFormFields.call(
        this,
        lhsCol,
        chart,
        "",
        options,
        [],
        true
      );

      this.addButton(
        bottomRow,
        isInit ? lang.addButton || "add" : lang.saveButton || "save",
        isInit ? "add" : "save",
        callback,
        popupDiv
      );
    },
    /**
     * Create annotation's form fields.
     * @private
     * @param {HTMLDOMElement} - div where inputs are placed
     * @param {Chart} - chart
     * @param {String} - name of parent to create chain of names
     * @param {Object} - options
     * @param {Array} - storage - array where all items are stored
     * @param {Boolean} - isRoot - recursive flag for root
     */
    addFormFields: function (
      parentDiv,
      chart,
      parentNode,
      options,
      storage,
      isRoot
    ) {
      var _self = this,
        addFormFields = this.annotations.addFormFields,
        addInput = this.addInput,
        lang = this.lang,
        parentFullName,
        titleName;

      objectEach(options, function (value, option) {
        // create name like params.styles.fontSize
        parentFullName = parentNode !== "" ? parentNode + "." + option : option;

        if (isObject(value)) {
          if (
            // value is object of options
            !isArray(value) ||
            // array of objects with params. i.e labels in Fibonacci
            (isArray(value) && isObject(value[0]))
          ) {
            titleName = lang[option] || option;

            if (!titleName.match(indexFilter)) {
              storage.push([true, titleName, parentDiv]);
            }

            addFormFields.call(
              _self,
              parentDiv,
              chart,
              parentFullName,
              value,
              storage,
              false
            );
          } else {
            storage.push([
              _self,
              parentFullName,
              "annotation",
              parentDiv,
              value,
            ]);
          }
        }
      });

      if (isRoot) {
        storage = storage.sort(function (a) {
          return a[1].match(/format/g) ? -1 : 1;
        });

        storage.forEach(function (genInput) {
          if (genInput[0] === true) {
            createElement(
              SPAN,
              {
                className: PREFIX + "annotation-title",
                innerHTML: genInput[1],
              },
              null,
              genInput[2]
            );
          } else {
            addInput.apply(genInput[0], genInput.splice(1));
          }
        });
      }
    },
  },
  indicators: {
    /**
     * Create indicator's form. It contains two tabs (ADD and EDIT) with
     * content.
     * @private
     * @param {Chart} - chart
     * @param {Object} - options
     * @param {Function} - on click callback
     */
    addForm: function (chart, options, callback) {
      var tabsContainers,
        indicators = this.indicators,
        lang = this.lang,
        buttonParentDiv;

      // add tabs
      this.tabs.init.call(this, chart);

      // get all tabs content divs
      tabsContainers = this.popup.container.querySelectorAll(
        "." + PREFIX + "tab-item-content"
      );

      // ADD tab
      this.addColsContainer(tabsContainers[0]);
      indicators.addIndicatorList.call(this, chart, tabsContainers[0], "add");

      buttonParentDiv = tabsContainers[0].querySelectorAll(
        "." + PREFIX + "popup-rhs-col"
      )[0];

      this.addButton(
        buttonParentDiv,
        lang.addButton || "add",
        "add",
        callback,
        buttonParentDiv
      );

      // EDIT tab
      this.addColsContainer(tabsContainers[1]);
      indicators.addIndicatorList.call(this, chart, tabsContainers[1], "edit");

      buttonParentDiv = tabsContainers[1].querySelectorAll(
        "." + PREFIX + "popup-rhs-col"
      )[0];

      this.addButton(
        buttonParentDiv,
        lang.saveButton || "save",
        "edit",
        callback,
        buttonParentDiv
      );
      this.addButton(
        buttonParentDiv,
        lang.removeButton || "remove",
        "remove",
        callback,
        buttonParentDiv
      );
    },
    /**
     * Create HTML list of all indicators (ADD mode) or added indicators
     * (EDIT mode).
     * @private
     * @param {Chart} - chart
     * @param {HTMLDOMElement} - container where list is added
     * @param {String} - 'edit' or 'add' mode
     */
    addIndicatorList: function (chart, parentDiv, listType) {
      var _self = this,
        lhsCol = parentDiv.querySelectorAll("." + PREFIX + "popup-lhs-col")[0],
        rhsCol = parentDiv.querySelectorAll("." + PREFIX + "popup-rhs-col")[0],
        isEdit = listType === "edit",
        series = isEdit
          ? chart.series // EDIT mode
          : chart.options.plotOptions, // ADD mode
        addFormFields = this.indicators.addFormFields,
        rhsColWrapper,
        indicatorList,
        item;

      // create wrapper for list
      indicatorList = createElement(
        UL,
        {
          className: PREFIX + "indicator-list",
        },
        null,
        lhsCol
      );

      rhsColWrapper = rhsCol.querySelectorAll(
        "." + PREFIX + "popup-rhs-col-wrapper"
      )[0];

      objectEach(series, function (serie, value) {
        var seriesOptions = serie.options;

        if (serie.params || (seriesOptions && seriesOptions.params)) {
          var indicatorNameType = _self.indicators.getNameType(serie, value),
            indicatorType = indicatorNameType.type;

          item = createElement(
            LI,
            {
              className: PREFIX + "indicator-list",
              innerHTML: indicatorNameType.name,
            },
            null,
            indicatorList
          );

          ["click", "touchstart"].forEach(function (eventName) {
            addEvent(item, eventName, function () {
              addFormFields.call(
                _self,
                chart,
                isEdit ? serie : series[indicatorType],
                indicatorNameType.type,
                rhsColWrapper
              );

              // add hidden input with series.id
              if (isEdit && serie.options) {
                createElement(
                  INPUT,
                  {
                    type: "hidden",
                    name: PREFIX + "id-" + indicatorType,
                    value: serie.options.id,
                  },
                  null,
                  rhsColWrapper
                ).setAttribute(PREFIX + "data-series-id", serie.options.id);
              }
            });
          });
        }
      });

      // select first item from the list
      if (indicatorList.childNodes.length > 0) {
        indicatorList.childNodes[0].click();
      }
    },
    /**
     * Extract full name and type of requested indicator.
     * @private
     * @param {Series} - series which name is needed.
     * (EDIT mode - defaultOptions.series, ADD mode - indicator series).
     * @param {String} - indicator type like: sma, ema, etc.
     * @return {Object} - series name and type like: sma, ema, etc.
     */
    getNameType: function (series, type) {
      var options = series.options,
        seriesTypes = H.seriesTypes,
        // add mode
        seriesName =
          (seriesTypes[type] && seriesTypes[type].prototype.nameBase) ||
          type.toUpperCase(),
        seriesType = type;

      // edit
      if (options && options.type) {
        seriesType = series.options.type;
        seriesName = series.name;
      }

      return {
        name: seriesName,
        type: seriesType,
      };
    },
    /**
     * List all series with unique ID. Its mandatory for indicators to set
     * correct linking.
     * @private
     * @param {String} - indicator type like: sma, ema, etc.
     * @param {String} - type of select i.e series or volume.
     * @param {Chart} - chart
     * @param {HTMLDOMElement} - element where created HTML list is added
     * @param {String} selectedOption
     *         optional param for default value in dropdown
     */
    listAllSeries: function (
      type,
      optionName,
      chart,
      parentDiv,
      selectedOption
    ) {
      var selectName = PREFIX + optionName + "-type-" + type,
        lang = this.lang,
        selectBox,
        seriesOptions;

      createElement(
        LABEL,
        {
          innerHTML: lang[optionName] || optionName,
          htmlFor: selectName,
        },
        null,
        parentDiv
      );

      // select type
      selectBox = createElement(
        SELECT,
        {
          name: selectName,
          className: PREFIX + "popup-field",
        },
        null,
        parentDiv
      );

      selectBox.setAttribute("id", PREFIX + "select-" + optionName);

      // list all series which have id - mandatory for creating indicator
      chart.series.forEach(function (serie) {
        seriesOptions = serie.options;

        if (
          !seriesOptions.params &&
          seriesOptions.id &&
          seriesOptions.id !== PREFIX + "navigator-series"
        ) {
          createElement(
            OPTION,
            {
              innerHTML: seriesOptions.name || seriesOptions.id,
              value: seriesOptions.id,
            },
            null,
            selectBox
          );
        }
      });

      if (defined(selectedOption)) {
        selectBox.value = selectedOption;
      }
    },
    /**
     * Create typical inputs for chosen indicator. Fields are extracted from
     * defaultOptions (ADD mode) or current indicator (ADD mode). Two extra
     * fields are added:
     * - hidden input - contains indicator type (required for callback)
     * - select - list of series which can be linked with indicator
     * @private
     * @param {Chart} - chart
     * @param {Series} - indicator
     * @param {String} - indicator type like: sma, ema, etc.
     * @param {HTMLDOMElement} - element where created HTML list is added
     */
    addFormFields: function (chart, series, seriesType, rhsColWrapper) {
      var fields = series.params || series.options.params,
        getNameType = this.indicators.getNameType;

      // reset current content
      rhsColWrapper.innerHTML = "";

      // create title (indicator name in the right column)
      createElement(
        H3,
        {
          className: PREFIX + "indicator-title",
          innerHTML: getNameType(series, seriesType).name,
        },
        null,
        rhsColWrapper
      );

      // input type
      createElement(
        INPUT,
        {
          type: "hidden",
          name: PREFIX + "type-" + seriesType,
          value: seriesType,
        },
        null,
        rhsColWrapper
      );

      // list all series with id
      this.indicators.listAllSeries.call(
        this,
        seriesType,
        "series",
        chart,
        rhsColWrapper,
        series.linkedParent && fields.volumeSeriesID
      );

      if (fields.volumeSeriesID) {
        this.indicators.listAllSeries.call(
          this,
          seriesType,
          "volume",
          chart,
          rhsColWrapper,
          series.linkedParent && series.linkedParent.options.id
        );
      }

      // add param fields
      this.indicators.addParamInputs.call(
        this,
        chart,
        "params",
        fields,
        seriesType,
        rhsColWrapper
      );
    },
    /**
     * Recurent function which lists all fields, from params object and
     * create them as inputs. Each input has unique `data-name` attribute,
     * which keeps chain of fields i.e params.styles.fontSize.
     * @private
     * @param {Chart} - chart
     * @param {String} - name of parent to create chain of names
     * @param {Series} - fields - params which are based for input create
     * @param {String} - indicator type like: sma, ema, etc.
     * @param {HTMLDOMElement} - element where created HTML list is added
     */
    addParamInputs: function (chart, parentNode, fields, type, parentDiv) {
      var _self = this,
        addParamInputs = this.indicators.addParamInputs,
        addInput = this.addInput,
        parentFullName;

      objectEach(fields, function (value, fieldName) {
        // create name like params.styles.fontSize
        parentFullName = parentNode + "." + fieldName;

        if (isObject(value)) {
          addParamInputs.call(
            _self,
            chart,
            parentFullName,
            value,
            type,
            parentDiv
          );
        } else if (
          // skip volume field which is created by addFormFields
          parentFullName !== "params.volumeSeriesID"
        ) {
          addInput.call(
            _self,
            parentFullName,
            type,
            parentDiv,
            [value, "text"] // all inputs are text type
          );
        }
      });
    },
    /**
     * Get amount of indicators added to chart.
     * @private
     * @return {Number} - Amount of indicators
     */
    getAmount: function () {
      var series = this.series,
        counter = 0;

      objectEach(series, function (serie) {
        var seriesOptions = serie.options;

        if (serie.params || (seriesOptions && seriesOptions.params)) {
          counter++;
        }
      });

      return counter;
    },
  },
  tabs: {
    /**
     * Init tabs. Create tab menu items, tabs containers
     * @private
     * @param {Chart} - reference to current chart
     */
    init: function (chart) {
      var tabs = this.tabs,
        indicatorsCount = this.indicators.getAmount.call(chart),
        firstTab; // run by default

      // create menu items
      firstTab = tabs.addMenuItem.call(this, "add");
      tabs.addMenuItem.call(this, "edit", indicatorsCount);

      // create tabs containers
      tabs.addContentItem.call(this, "add");
      tabs.addContentItem.call(this, "edit");

      tabs.switchTabs.call(this, indicatorsCount);

      // activate first tab
      tabs.selectTab.call(this, firstTab, 0);
    },
    /**
     * Create tab menu item
     * @private
     * @param {String} - `add` or `edit`
     * @param {Number} - Disable tab when 0
     * @return {HTMLDOMElement} - created HTML tab-menu element
     */
    addMenuItem: function (tabName, disableTab) {
      var popupDiv = this.popup.container,
        className = PREFIX + "tab-item",
        lang = this.lang,
        menuItem;

      if (disableTab === 0) {
        className += " " + PREFIX + "tab-disabled";
      }

      // tab 1
      menuItem = createElement(
        SPAN,
        {
          innerHTML: lang[tabName + "Button"] || tabName,
          className: className,
        },
        null,
        popupDiv
      );

      menuItem.setAttribute(PREFIX + "data-tab-type", tabName);

      return menuItem;
    },
    /**
     * Create tab content
     * @private
     * @return {HTMLDOMElement} - created HTML tab-content element
     */
    addContentItem: function () {
      var popupDiv = this.popup.container;

      return createElement(
        DIV,
        {
          className: PREFIX + "tab-item-content",
        },
        null,
        popupDiv
      );
    },
    /**
     * Add click event to each tab
     * @private
     * @param {Number} - Disable tab when 0
     */
    switchTabs: function (disableTab) {
      var _self = this,
        popupDiv = this.popup.container,
        tabs = popupDiv.querySelectorAll("." + PREFIX + "tab-item"),
        dataParam;

      tabs.forEach(function (tab, i) {
        dataParam = tab.getAttribute(PREFIX + "data-tab-type");

        if (dataParam === "edit" && disableTab === 0) {
          return;
        }

        ["click", "touchstart"].forEach(function (eventName) {
          addEvent(tab, eventName, function () {
            // reset class on other elements
            _self.tabs.deselectAll.call(_self);
            _self.tabs.selectTab.call(_self, this, i);
          });
        });
      });
    },
    /**
     * Set tab as visible
     * @private
     * @param {HTMLDOMElement} - current tab
     * @param {Number} - Index of tab in menu
     */
    selectTab: function (tab, index) {
      var allTabs = this.popup.container.querySelectorAll(
        "." + PREFIX + "tab-item-content"
      );

      tab.className += " " + PREFIX + "tab-item-active";
      allTabs[index].className += " " + PREFIX + "tab-item-show";
    },
    /**
     * Set all tabs as invisible.
     * @private
     */
    deselectAll: function () {
      var popupDiv = this.popup.container,
        tabs = popupDiv.querySelectorAll("." + PREFIX + "tab-item"),
        tabsContent = popupDiv.querySelectorAll(
          "." + PREFIX + "tab-item-content"
        ),
        i;

      for (i = 0; i < tabs.length; i++) {
        tabs[i].classList.remove(PREFIX + "tab-item-active");
        tabsContent[i].classList.remove(PREFIX + "tab-item-show");
      }
    },
  },
};

addEvent(H.NavigationBindings, "showPopup", function (config) {
  if (!this.popup) {
    // Add popup to main container
    this.popup = new H.Popup(
      this.chart.container,
      this.chart.options.navigation.iconsURL ||
        (this.chart.options.stockTools &&
          this.chart.options.stockTools.gui.iconsURL) ||
        "https://code.highcharts.com/8.0.0/gfx/stock-icons/"
    );
  }

  this.popup.showForm(
    config.formType,
    this.chart,
    config.options,
    config.onSubmit
  );
});

addEvent(H.NavigationBindings, "closePopup", function () {
  if (this.popup) {
    this.popup.closePopup();
  }
});
